package com.simple.mqtt.common.tool;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Optional;

/**
 * 日志工具类，支持彩色控制台输出
 * 提供简单的日志功能，使用ANSI颜色代码提高可读性
 */
public class LogTool {
    // ANSI color codes
    private static final String RESET = "\u001B[0m";
    private static final String BLACK = "\u001B[30m";
    private static final String RED = "\u001B[31m";
    private static final String GREEN = "\u001B[32m";
    private static final String YELLOW = "\u001B[33m";
    private static final String BLUE = "\u001B[34m";
    private static final String PURPLE = "\u001B[35m";
    private static final String CYAN = "\u001B[36m";
    private static final String WHITE = "\u001B[37m";
    public static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 记录INFO级别日志（绿色）
     * @param message 日志消息
     */
    public static void info(Object message) {
        StackTraceElement caller = getCallerInfo();
        String className = getSimpleClassName(caller.getClassName());
        String formattedMessage = formatMessage(GREEN, String.valueOf(message), "INFO", className);
        System.out.print(formattedMessage);
    }

    /**
     * 记录带格式的INFO级别日志
     * @param format 消息格式
     * @param arguments 格式参数
     */
    public static void info(String format, Object... arguments) {
        info(formatMessage(format, arguments));
    }

    /**
     * 记录ERROR级别日志（红色）
     * @param message 日志消息
     */
    public static void error(Object message) {
        StackTraceElement caller = getCallerInfo();
        String className = getSimpleClassName(caller.getClassName());
        String formattedMessage = formatMessage(RED, String.valueOf(message), "ERROR", className);
        System.err.print(formattedMessage);
    }

    /**
     * 记录带格式的ERROR级别日志
     * @param format 消息格式
     * @param arguments 格式参数
     */
    public static void error(String format, Object... arguments) {
        error(formatMessage(format, arguments));
    }

    /**
     * 记录带异常的ERROR级别日志
     * @param message 错误消息
     * @param throwable 要记录的异常
     */
    public static void error(Object message, Throwable throwable) {
        error(message);
        if (throwable != null) {
            throwable.printStackTrace();
        }
    }

    /**
     * 记录WARN级别日志（黄色）
     * @param message 日志消息
     */
    public static void warn(Object message) {
        StackTraceElement caller = getCallerInfo();
        String className = getSimpleClassName(caller.getClassName());
        String formattedMessage = formatMessage(YELLOW, String.valueOf(message), "WARN", className);
        System.out.print(formattedMessage);
    }

    /**
     * 记录带格式的WARN级别日志
     * @param format 消息格式
     * @param arguments 格式参数
     */
    public static void warn(String format, Object... arguments) {
        warn(formatMessage(format, arguments));
    }

    /**
     * 记录DEBUG级别日志（紫色）
     * @param message 日志消息
     */
    public static void debug(Object message) {
        StackTraceElement caller = getCallerInfo();
        String className = getSimpleClassName(caller.getClassName());
        String formattedMessage = formatMessage(PURPLE, String.valueOf(message), "DEBUG", className);
        System.out.print(formattedMessage);
    }

    /**
     * 记录带格式的DEBUG级别日志
     * @param format 消息格式
     * @param arguments 格式参数
     */
    public static void debug(String format, Object... arguments) {
        debug(formatMessage(format, arguments));
    }

    /**
     * 格式化消息内容（处理参数替换）
     * @param format 消息格式
     * @param arguments 格式参数
     * @return 格式化后的消息
     */
    private static String formatMessage(String format, Object... arguments) {
        if (arguments == null || arguments.length == 0) {
            return format;
        }
        String result = format;
        for (Object arg : arguments) {
            result = result.replaceFirst("\\{\\}", String.valueOf(arg != null ? arg : "null"));
        }
        return result;
    }

    /**
     * 格式化完整日志消息（整行着色）
     * @param colorCode ANSI颜色代码
     * @param message 日志消息
     * @param level 日志级别
     * @param className 类名
     * @return 格式化后的日志消息
     */
    private static String formatMessage(String colorCode, String message, String level, String className) {
        String rawMessage = String.format("[%s]-[%s]-[%s]-[%s]+>: %s%n",
                "MQTT",
                level,
                getFormattedDate(),
                className,
                message
        );
        return colorCode + rawMessage + RESET;
    }

    /**
     * 获取格式化日期
     * @return 格式化日期字符串
     */
    private static String getFormattedDate() {
        try {
            return SIMPLE_DATE_FORMAT.format(new Date());
        } catch (Exception e) {
            return LocalDateTime.now().toString();
        }
    }

    /**
     * 获取简单类名
     * @param fullClassName 完整类名
     * @return 简单类名
     */
    private static String getSimpleClassName(String fullClassName) {
        return Optional.ofNullable(fullClassName)
                .filter(s -> !s.isEmpty())
                .orElse("MAIN");
    }

    /**
     * 从堆栈跟踪获取调用者信息
     * @return 调用者的堆栈跟踪元素
     */
    private static StackTraceElement getCallerInfo() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (int i = 4; i < stackTrace.length; i++) {
            StackTraceElement element = stackTrace[i];
            String className = element.getClassName();
            // Skip LogTool itself and reflection classes
            if (!className.startsWith("com.simple.mqtt")) {
                continue;
            }
            return element;
        }
        return stackTrace.length > 0 ? stackTrace[stackTrace.length - 1] : null;
    }
}